package com.github.kezhenxu94.playground.java.miscellaneous;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

import org.junit.Test;

public class ExploreReference {

	/**
	 * WeakReference: 不会影响垃圾回收器对该对象回收，一旦该对象在除了 WeakReference 之外不可达，下一次垃圾回收都会回收
	 * 该对象。
	 */
	@Test
	public void testWeakReference() {
		final ReferenceQueue<Object> rq = new ReferenceQueue<>();
		new Thread(() -> {
			try {
				// 被加入到 ReferenceQueue 的是 WeakReference 而不是 Object
				System.out.println(rq.remove());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}).start();
		Object obj = new Object();
		Reference<Object> objRef = new WeakReference<Object>(obj, rq);
		obj = null;
		System.out.println(objRef.get());
		System.gc();
		System.out.println(objRef.get());
	}

	/**
	 * SoftReference: 只有在垃圾回收器抛出 OutOfMemoryError 之前清除 SoftReference。
	 * 
	 * -Xmx1m
	 */
	@Test
	public void testSoftReference() {
		final ReferenceQueue<Object> rq = new ReferenceQueue<>();
		new Thread(() -> {
			try {
				// 被加入到 ReferenceQueue 的是 SoftReference 而不是 Object
				System.out.println(rq.remove());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}).start();
		Object obj = new Object();
		Reference<Object> objRef = new SoftReference<Object>(obj, rq);
		obj = null;
		System.out.println(objRef.get());
		System.gc();
		System.out.println(objRef.get());
		// 此时内存足够，不会清除 SoftReference
		@SuppressWarnings("unused")
		byte[] bs = new byte[1024 * 1024 * 1024];
		// 模拟分配大对象，导致内存不够，抛出 OOM 之前会清除 SoftReference
		System.gc();
		System.out.println(objRef.get());
	}
}
